feat(cli): prompt in a GUI instead of the console, plus a global approval policy#122
Draft
domenkozar wants to merge 5 commits into
Draft
feat(cli): prompt in a GUI instead of the console, plus a global approval policy#122domenkozar wants to merge 5 commits into
domenkozar wants to merge 5 commits into
Conversation
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
secretspec | e378150 | Commit Preview URL Branch Preview URL |
Jul 08 2026, 10:57 PM |
Add pinentry-based trusted value entry for `set` and `check`, and require explicit human approval before releasing secrets. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
domenkozar
force-pushed
the
feat/trusted-prompts
branch
from
July 6, 2026 16:38
69ed760 to
303cc2e
Compare
Add an `egui-pinentry` crate: a passphrase and confirmation dialog drawn with egui rasterized on the CPU (no GPU, no OpenGL/Vulkan) via softbuffer, with an X11 keyboard grab released via a Drop guard, keystrokes fed into a zeroizing buffer (no egui TextEdit undo retention), and a `SecretString` result. One event loop is reused across dialogs. The dialog layout is covered by headless egui_kittest tests. devenv gains the windowing libs on LD_LIBRARY_PATH so it runs inside the dev shell. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Route trusted value entry and approval through the egui-pinentry crate behind a `gui-prompt` feature (enabled by `cli`), so the CLI shows a self-contained dialog and no longer needs an external pinentry binary. Without the feature it falls back to a pinentry binary, and with no display to a `/dev/tty` prompt. Keep the GUI stack out of the language SDK cdylibs: secretspec-ffi, -py, and -node now depend on the library without default features and re-enable only the providers they resolve from, so `gui-prompt` (and egui) is never pulled into those artifacts. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
domenkozar
force-pushed
the
feat/trusted-prompts
branch
from
July 8, 2026 21:09
36b8d22 to
d1144f4
Compare
domenkozar
force-pushed
the
feat/trusted-prompts
branch
from
July 8, 2026 21:19
d1144f4 to
c420c82
Compare
…oval policy Drop the per-secret `interactive` flag and the `set --ask` flag. `set` and the `check` fill loop now detect whether this machine can show a GUI prompt (a display server plus a dialog to draw with: the built-in one, or a pinentry binary without the `gui-prompt` feature) and prefer it over reading the console whenever it can. This forces a precedence choice the opt-in used to sidestep, since a non-terminal stdin means both "a script is piping a value" and "an agent invoked me with a pipe it controls". Resolved toward the security property: inline values win, then the GUI prompt, then a terminal prompt, then a piped stdin. On a machine with a display, `echo v | secretspec set KEY` now opens a dialog rather than storing `v`; pass the value inline to seed a secret from a script. When detection sees a display but the dialog cannot open on it and there is no controlling terminal either, fail closed with an actionable message rather than fall back to the caller-controlled stdin. Also let `require_approval` be set once for every project, as `[defaults].require_approval` in the user's config, so an operator can ask to be prompted whenever an agent releases secrets without editing each `secretspec.toml`. The project and user policies combine by taking whichever is stricter (`false` < `"agents"` < `true`), making this a floor rather than a fallback: a project cannot switch off the approval an operator configured for themselves, and an operator cannot switch off the approval a project demands of every clone. A plain fallback would have let any project's explicit `require_approval = false`, the default value, silently disable the operator's safeguard. `secretspec config show` prints the user-level policy. Correct the docs to describe the built-in GUI dialog rather than an external pinentry binary, and to note that `require_approval` gates `import` alongside `run` and `get`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
domenkozar
force-pushed
the
feat/trusted-prompts
branch
from
July 8, 2026 22:10
c420c82 to
38dd77f
Compare
…ell evaluates The LD_LIBRARY_PATH for egui-pinentry's X11/Wayland windowing stack referenced wayland + xorg.* unconditionally. Those packages are Linux-only, so evaluating the devenv shell on a darwin host aborted with "wayland is not available on the requested hostPlatform", failing the macOS test job (which then cancelled the Linux one). Guard the block with lib.optionalAttrs stdenv.isLinux; the libs are only needed on Linux anyway, since macOS windowing is native Cocoa. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
domenkozar
marked this pull request as draft
July 8, 2026 23:43
Member
Author
|
Blocked on dsociative/pinentry-egui#1 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Trusted local prompts for value entry and secret release, so a CI job or coding agent can trigger secret operations without ever seeing the values, and cannot self-approve.
interactive = true(orsecretspec set --ask) to type its value into a trusted dialog instead of stdin.require_approvalin[project](true/false/"agents") to require human approval at that same trusted dialog beforesecretspec runinjects secrets orsecretspec get/importreleases one.Trusted channel: a built-in GUI
The CLI renders the prompt with a self-contained GUI dialog and no longer needs an external
pinentrybinary installed. The channel resolves as:egui-pinentrydialog (with thegui-promptfeature, enabled bycli) — a small window drawn with egui on the CPU (no GPU / OpenGL / Vulkan), that on X11 grabs the keyboard to resist snooping.pinentrybinary when built withoutgui-prompt./dev/ttyprompt when no display is available. A detected agent is refused any terminal-bound channel.New crate:
egui-pinentryA self-contained passphrase + confirmation dialog crate (its own commit; publishable independently):
softbuffer+egui_software_backend(no GPU crates in the tree).XGrabKeyboard, released via aDropguard; no-op on Wayland/macOS/Windows.zeroize::Zeroizingbuffer (never an eguiTextEdit), so the secret is not retained in egui's widget/undo state; returned as aSecretString.run_app_on_demand).egui_kittest.SDKs stay lean
secretspec-ffi,-py, and-nodenow depend on the library withdefault-features = false(+ the providers they resolve from), sogui-promptand the ~78 GUI crates are never pulled into the language SDK cdylibs. Verified: building the ffi crate compiles egui-pinentry 0×, the CLI 1×.Notes
interactivesecret (orset --ask) never reads a piped value:echo v | secretspec set KEYprompts rather than storingv. Pass it inline (secretspec set KEY "$V") or leave the secret non-interactive.🤖 Generated with Claude Code